package com.carl.zeus.config.websocket;

import com.alibaba.fastjson.JSON;
import com.carl.zeus.common.emnu.MessageType;
import com.carl.zeus.common.emnu.SendType;
import com.carl.zeus.common.emnu.UserStatus;
import com.carl.zeus.model.system.SysUser;
import com.carl.zeus.model.system.SysUserChat;
import com.carl.zeus.server.system.SysUserChatService;
import com.carl.zeus.server.system.SysUserService;
import org.apache.shiro.session.mgt.SimpleSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

@ServerEndpoint(value="/websocket", configurator = GetHttpSessionConfigurator.class)
@Component
public class MyWebSocket {
	
	private static final String REDIS_KEY = "shiro_redis_session:";
	
	@Autowired
	private SysUserChatService sysUserChatService;

	@Autowired
	private SysUserService sysUserService;
	
	@Autowired
	private RedisTemplate<String, SimpleSession> redisTemplate;
	
	// 静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
	private static int onlineCount = 0;

	// concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。
	private static Set<MyWebSocket>	onlineUsers	= new CopyOnWriteArraySet<>();

	// 与某个客户端的连接会话，需要通过它来给客户端发送数据
	private Session	session;
	
	private HttpSession httpSession;
	
	/**
	 * 连接建立成功调用的方法
	 * @throws IOException 
	 */
	@OnOpen
	public void onOpen(Session session,EndpointConfig config) throws IOException {
		if(sysUserChatService == null){
			sysUserChatService = WebSocketConfig.appContext.getBean(SysUserChatService.class);
        }
		if(sysUserService == null){
			sysUserService = WebSocketConfig.appContext.getBean(SysUserService.class);
		}
		if(redisTemplate == null){
			redisTemplate = (RedisTemplate<String, SimpleSession>) WebSocketConfig.appContext.getBean("redisSimpleSessionTemplate");
        }
		httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
		SimpleSession simpleSession = redisTemplate.opsForValue().get(REDIS_KEY+httpSession.getId());
        SysUser user = (SysUser) simpleSession.getAttribute("user");
		//保存在线列表
        IMManager.addUser(user, session);
        System.out.println("当前在线用户：" + IMManager.getOnlineNum());
        System.out.println("缓存中的用户个数：" + IMManager.getCashNum());
        try {
        	// 获取用户未读消息 列表聊天,上线的时候推送给用户
			List<SysUserChat> list = sysUserChatService.findUnSendList(user.getId(), SendType.UNSENT.getType(), MessageType.FRIEND.getType());
			if(list != null && list.size() > 0){
				list.stream().forEach(tm -> {
					try {
						session.getBasicRemote().sendText(JSON.toJSONString(tm));
						tm.setSendType(SendType.SENT.getType());
						sysUserChatService.insert(tm);
					} catch (IOException e) {
						e.printStackTrace();
					}
				});
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		this.session = session;
		onlineUsers.add( this ); // 加入set中
		addOnlineCount();
		System.out.println( "有新连接加入！当前在线人数为" + onlineCount );
		sendMessage(JSON.toJSONString(user) );
	}

	/**
	 * 连接关闭调用的方法
	 */
	@OnClose
	public void onClose(Session session) {
		SocketUser su = IMManager.getSocketUserBySeesionId(session.getId());
        if (su != null) {
            su.getUser().setState(UserStatus.NotOnline);
            System.out.println(su.getUser().getUsername()+ ":用户掉线");
        }
        IMManager.removeUser(su, session);
		onlineUsers.remove( this ); // 从set中删除
		subOnlineCount(); // 在线数减1
		for (MyWebSocket item : onlineUsers) {  //发送给所有用户 告诉这个用户掉线了
			try {
				item.sendMessage( httpSession.getId() );
			} catch (IOException e) {
				continue;
			}
		}
		System.out.println( "有一连接关闭！当前在线人数为" + getOnlineCount() );
	}

	/**
	 * 收到客户端消息后调用的方法
	 * @param message 客户端发送过来的消息
	 * @throws IOException
	 */
	@OnMessage
	public void onMessage(String message, Session session) throws IOException {
		System.out.println( "来自客户端的消息:" + message );
//		UserVO userVO = JSON.parseObject(message, UserVO.class);
////		//发送人
////		SysUser fromUser = userMapper.findByUsername(userVO.getUsername());
////		Set<String> allUser = userMapper.selectByUsernames();
////		Set<String> onlineUser = IMManager.getUsernames();
////		userVO.setName(fromUser.getName());
////		userVO.setFromAvatar(fromUser.getAvatar());
////		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
////		userVO.setDate(df.format(new Date()));
////		sendInfo(JSON.toJSONString(userVO));

//		SysUserChat tm = null;
//        try {
//            //SocketMessage sm = JSON.parseObject(message, SocketMessage.class);
//            //得到接收的对象
//            //SysUser user = sm.getUser();
////            tm = sm.getMessage();
////            if(user != null && user.getId()!=null){
////            	IMManager.addUser(user, session);
////            }
//            if (tm == null || tm.getSendId()!=null) {
//                tm = null;
//            } else {
//                System.out.println("the tm:" + tm.toString());
//                tm.setSendType(SendType.UNSENT);
//                tm.setCreateTime(new Date());
//                if (MessageType.FRIEND == tm.getType()) {
//                    SocketUser su = IMManager.getSocketUserByUserId(tm.getSendId().toString());
//                    if (su != null && su.getSession() != null && su.getSession().isOpen()) {
//                        su.getSession().getBasicRemote().sendText(JSON.toJSONString(tm));
//                        System.out.println("send message to "+tm.getSendName());
//                        tm.setSendType(SendType.SENT);
//                    }
//                } else if (MessageType.GROUP == tm.getType()) {
//                    List<String> ids = sm.getGroupIds();
//                    if(ids != null && ids.size() > 0){
//                    	for (String sendId : ids) {
//                    		if(tm.getUserId().equals(sendId)){
//                    			continue;
//                    		}
//                    		SocketUser su = IMManager.getSocketUserByUserId(sendId);
//                    		if(su != null && su.getSession()!= null && su.getSession().isOpen()){
//                    			try {
//                                    su.getSession().getBasicRemote().sendText(JSON.toJSONString(tm));
//                                } catch (IOException ie) {
//                                    ie.printStackTrace();
//                                }
//                    		}
//						}
//                    }
//                    tm.setSendType(SendType.SENT);
//                }
//            }
//            if (tm != null && userChatRepository != null) {
//            	userChatRepository.save(tm);
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//		JSONObject obj = JSON.parseObject( message );
//		UserVO msg = (UserVO) JSONObject.toJavaObject( obj, UserVO.class );
//		if (StringUtils.isNotEmpty(msg.getType())) {
//			this.sendInfo( JSON.toJSONString(msg) );
//		} else {
//			session.getAsyncRemote().sendText( message );
//			// this.sendToUserMessage( , message );
//		}

	}

	// 发生错误时调用
	@OnError
	public void onError(Session session, Throwable error) {
		onClose(session);
		System.out.println( "发生错误" );
		error.printStackTrace();
	}

	public void sendMessage(String message) throws IOException {
		this.session.getBasicRemote().sendText( message );
	}

	// 单向发送消息
	public void sendToUserMessage(MyWebSocket item, String message) throws IOException {
		item.sendMessage( message );
	}

	// 群发自定义消息
	public void sendInfo(String message) throws IOException {
		for (MyWebSocket item : onlineUsers) {
			try {
				item.sendMessage( message );
			} catch (IOException e) {
				continue;
			}
		}
	}

	public static synchronized int getOnlineCount() {
		return onlineCount;
	}

	public static synchronized void addOnlineCount() {
		MyWebSocket.onlineCount++;
	}

	public static synchronized void subOnlineCount() {
		MyWebSocket.onlineCount--;
	}
}
